package pokpok.action;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.struts2.ServletActionContext;

import pokpok.dao.JoueurDAO;
import pokpok.dao.ResultatDAO;
import pokpok.dao.TournoiDAO;
import pokpok.domaine.Joueur;
import pokpok.domaine.Resultat;
import pokpok.domaine.Tournoi;
import pokpok.service.JoueurComparator;
import pokpok.service.ResultatComparator;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class TournoiAction extends ActionSupport {

	/**
	 * 
	 */
	private static final long serialVersionUID = -7429759453523069767L;

	private List<Tournoi> tournois;

	private String dateString;
	private String buyinString;
	private String recaveString;
	private String addonString;
	private String nbJoueursString;

	private Integer saison;
	private List<Integer> saisons;

	private Tournoi tournoi;
	private String keyTournoi;

	private boolean error;
	private String messageError;

	private List<Joueur> joueurs;
	private List<Resultat> resultatsTries;

	private Integer totalRecaves;
	private Integer totalAddOns;
	private Integer totalMise;

	public String init() {
		TournoiDAO tDAO = new TournoiDAO();
		List<Tournoi> all = tDAO.findAll();
		initSaisons(all, false);
		if (saison == null) {
			saison = saisons.get(saisons.size() - 1);
		}
		if (saison == 0) {
			tournois = all;
			return SUCCESS;
		}
		tournois = new ArrayList<Tournoi>();
		for (Tournoi tournoi : all) {
			if (tournoi.getSaison() != null
					&& tournoi.getSaison().equals(saison)) {
				tournois.add(tournoi);
			}
		}
		return SUCCESS;
	}

	public String initCreer() {
		dateString = new SimpleDateFormat("dd/MM/yyyy").format(new Date());
		buyinString = "10";
		recaveString = "10";
		addonString = "10";
		TournoiDAO tDAO = new TournoiDAO();
		List<Tournoi> all = tDAO.findAll();
		initSaisons(all, true);
		return SUCCESS;
	}

	public String initModifier() {
		TournoiDAO tDAO = new TournoiDAO();
		Key key = KeyFactory.stringToKey(keyTournoi);
		tournoi = tDAO.findById(key);
		dateString = new SimpleDateFormat("dd/MM/yyyy").format(tournoi
				.getDate());
		buyinString = "" + tournoi.getBuyin();
		recaveString = "" + tournoi.getRecave();
		addonString = "" + tournoi.getAddon();
		nbJoueursString = "" + tournoi.getNbJoueurs();
		List<Tournoi> all = tDAO.findAll();
		initSaisons(all, true);
		saison = tournoi.getSaison();
		return SUCCESS;
	}

	public String validerCreer() {
		Date d = null;
		Integer buyin = null;
		Integer recave = null;
		Integer addon = null;
		Integer nbJoueurs = null;
		error = false;
		messageError = "";
		try {
			d = new SimpleDateFormat("dd/MM/yyyy").parse(dateString);
		} catch (ParseException e) {
			error = true;
			messageError = "La date n'est pas au bon format.";
		}
		try {
			buyin = Integer.parseInt(buyinString);
		} catch (NumberFormatException e) {
			error = true;
			if (!"".equals(messageError)) {
				messageError = messageError + "<BR/>";
			}
			messageError = messageError + "Le buy-in n'est pas au bon format";
		}
		try {
			recave = Integer.parseInt(recaveString);
		} catch (NumberFormatException e) {
			error = true;
			if (!"".equals(messageError)) {
				messageError = messageError + "<BR/>";
			}
			messageError = messageError + "La recave n'est pas au bon format";
		}
		try {
			addon = Integer.parseInt(addonString);
		} catch (NumberFormatException e) {
			error = true;
			if (!"".equals(messageError)) {
				messageError = messageError + "<BR/>";
			}
			messageError = messageError + "L'add-on n'est pas au bon format";
		}
		try {
			nbJoueurs = Integer.parseInt(nbJoueursString);
		} catch (NumberFormatException e) {
			error = true;
			if (!"".equals(messageError)) {
				messageError = messageError + "<BR/>";
			}
			messageError = messageError
					+ "Le nombre de joueurs n'est pas au bon format";
		}
		if (error) {
			return INPUT;
		} else {
			tournoi = new Tournoi(d, buyin, recave, addon, nbJoueurs, saison);
			JoueurDAO jDAO = new JoueurDAO();
			joueurs = jDAO.findAll();
			Collections.sort(joueurs, new JoueurComparator());
			return SUCCESS;
		}
	}

	public String validerModifier() {
		Date d = null;
		Integer buyin = null;
		Integer recave = null;
		Integer addon = null;
		Integer nbJoueurs = null;
		error = false;
		messageError = "";
		try {
			d = new SimpleDateFormat("dd/MM/yyyy").parse(dateString);
		} catch (ParseException e) {
			error = true;
			messageError = "La date n'est pas au bon format.";
		}
		try {
			buyin = Integer.parseInt(buyinString);
		} catch (NumberFormatException e) {
			error = true;
			if (!"".equals(messageError)) {
				messageError = messageError + "<BR/>";
			}
			messageError = messageError + "Le buy-in n'est pas au bon format";
		}
		try {
			recave = Integer.parseInt(recaveString);
		} catch (NumberFormatException e) {
			error = true;
			if (!"".equals(messageError)) {
				messageError = messageError + "<BR/>";
			}
			messageError = messageError + "La recave n'est pas au bon format";
		}
		try {
			addon = Integer.parseInt(addonString);
		} catch (NumberFormatException e) {
			error = true;
			if (!"".equals(messageError)) {
				messageError = messageError + "<BR/>";
			}
			messageError = messageError + "L'add-on n'est pas au bon format";
		}
		try {
			nbJoueurs = Integer.parseInt(nbJoueursString);
		} catch (NumberFormatException e) {
			error = true;
			if (!"".equals(messageError)) {
				messageError = messageError + "<BR/>";
			}
			messageError = messageError
					+ "Le nombre de joueurs n'est pas au bon format";
		}
		if (error) {
			return INPUT;
		} else {
			tournoi = new Tournoi(d, buyin, recave, addon, nbJoueurs, saison);
			Map<String, Object> context = new HashMap<String, Object>();
			ResultatDAO rDAO = new ResultatDAO();
			TournoiDAO tDAO = new TournoiDAO();
			JoueurDAO jDAO = new JoueurDAO();
			Key key = KeyFactory.stringToKey(keyTournoi);
			Tournoi t = tDAO.findById(key);
			List<Resultat> resultats = rDAO.findByTournoi(t);
			for (Resultat resultat : resultats) {
				Integer position = resultat.getPosition();
				context.put("key" + position,
						KeyFactory.keyToString(resultat.getKeyJoueur()));
				context.put("recave" + position, resultat.getNbRecaves());
				if (resultat.isAddon()) {
					context.put("addon" + position, true);
				}
				context.put("gain" + position, resultat.getGain());
			}
			ActionContext.getContext().getValueStack().push(context);
			joueurs = jDAO.findAll();
			Collections.sort(joueurs, new JoueurComparator());
			return SUCCESS;
		}
	}

	public String validerCreer2() throws ParseException {
		Date d = new SimpleDateFormat("dd/MM/yyyy").parse(dateString);
		Integer buyin = Integer.parseInt(buyinString);
		Integer recave = Integer.parseInt(recaveString);
		Integer addon = Integer.parseInt(addonString);
		Integer nbJoueurs = Integer.parseInt(nbJoueursString);
		tournoi = new Tournoi(d, buyin, recave, addon, nbJoueurs, saison);
		error = false;
		messageError = "";
		Set<Resultat> resultats = new HashSet<Resultat>();

		Integer miseDistribuee = 0;
		Integer miseCalculee = 0;

		for (int position = 1; position < nbJoueurs + 1; position++) {
			Key key = null;
			Integer resultRecave = null;
			Integer resultGain = null;
			String keyJoueur = (String) ServletActionContext.getRequest()
					.getParameter("key" + position);
			if (keyJoueur == null || keyJoueur.equals("-1")) {
				error = true;
				if (!"".equals(messageError)) {
					messageError = messageError + "<BR/>";
				}
				messageError = messageError
						+ "Il faut choisir un joueur pour la position "
						+ position;
			} else {
				key = KeyFactory.stringToKey(keyJoueur);
			}
			String resultRecaveString = (String) ServletActionContext
					.getRequest().getParameter("recave" + position);
			Boolean resultAddOn = !(ServletActionContext.getRequest()
					.getParameter("addon" + position) == null);
			String resultGainString = (String) ServletActionContext
					.getRequest().getParameter("gain" + position);
			try {
				resultRecave = Integer.parseInt(resultRecaveString);
			} catch (NumberFormatException e) {
				error = true;
				if (!"".equals(messageError)) {
					messageError = messageError + "<BR/>";
				}
				messageError = messageError
						+ "Le nombre de recaves n'est pas au bon format pour le joueur en position "
						+ position;
			}
			try {
				resultGain = Integer.parseInt(resultGainString);
			} catch (NumberFormatException e) {
				error = true;
				if (!"".equals(messageError)) {
					messageError = messageError + "<BR/>";
				}
				messageError = messageError
						+ "Le gain n'est pas au bon format pour le joueur en position "
						+ position;
			}
			if (!error) {
				Resultat resultat = new Resultat(key, position, resultRecave,
						resultAddOn, resultGain);
				resultats.add(resultat);
				miseCalculee = miseCalculee + buyin;
				miseCalculee = miseCalculee + (resultRecave * recave);
				if (resultAddOn) {
					miseCalculee = miseCalculee + addon;
				}
				miseDistribuee = miseDistribuee + resultGain;
			}
		}

		if (!error) {
			if (!miseCalculee.equals(miseDistribuee)) {
				error = true;
				messageError = "Incohérence : total des mise des joueurs = "
						+ miseCalculee + " / total des gains = "
						+ miseDistribuee;
			}
		}

		if (error) {
			JoueurDAO jDAO = new JoueurDAO();
			joueurs = jDAO.findAll();
			Map<String, Object> context = new HashMap<String, Object>();
			for (int position = 1; position < nbJoueurs + 1; position++) {
				context.put("key" + position, (String) ServletActionContext
						.getRequest().getParameter("key" + position));
				context.put("recave" + position, (String) ServletActionContext
						.getRequest().getParameter("recave" + position));
				context.put("addon" + position, (String) ServletActionContext
						.getRequest().getParameter("addon" + position));
				context.put("gain" + position, (String) ServletActionContext
						.getRequest().getParameter("gain" + position));
			}
			ActionContext.getContext().getValueStack().push(context);
			return INPUT;
		} else {
			ResultatDAO rDAO = new ResultatDAO();
			TournoiDAO tDAO = new TournoiDAO();
			tournoi = tDAO.save(tournoi);
			for (Resultat resultat : resultats) {
				resultat.setKeyTournoi(tournoi.getId());
				rDAO.save(resultat);
			}
			resultatsTries = new ArrayList<Resultat>(resultats);
			Collections.sort(resultatsTries, new ResultatComparator());
			return SUCCESS;
		}
	}

	public String validerModifier2() throws ParseException {
		Date d = new SimpleDateFormat("dd/MM/yyyy").parse(dateString);
		Integer buyin = Integer.parseInt(buyinString);
		Integer recave = Integer.parseInt(recaveString);
		Integer addon = Integer.parseInt(addonString);
		Integer nbJoueurs = Integer.parseInt(nbJoueursString);
		Tournoi newValue = new Tournoi(d, buyin, recave, addon, nbJoueurs,
				saison);
		error = false;
		messageError = "";
		Set<Resultat> resultats = new HashSet<Resultat>();

		Integer miseDistribuee = 0;
		Integer miseCalculee = 0;

		for (int position = 1; position < nbJoueurs + 1; position++) {
			Key key = null;
			Integer resultRecave = null;
			Integer resultGain = null;
			String keyJoueur = (String) ServletActionContext.getRequest()
					.getParameter("key" + position);
			if (keyJoueur == null || keyJoueur.equals("-1")) {
				error = true;
				if (!"".equals(messageError)) {
					messageError = messageError + "<BR/>";
				}
				messageError = messageError
						+ "Il faut choisir un joueur pour la position "
						+ position;
			} else {
				key = KeyFactory.stringToKey(keyJoueur);
			}
			String resultRecaveString = (String) ServletActionContext
					.getRequest().getParameter("recave" + position);
			Boolean resultAddOn = !(ServletActionContext.getRequest()
					.getParameter("addon" + position) == null);
			String resultGainString = (String) ServletActionContext
					.getRequest().getParameter("gain" + position);
			try {
				resultRecave = Integer.parseInt(resultRecaveString);
			} catch (NumberFormatException e) {
				error = true;
				if (!"".equals(messageError)) {
					messageError = messageError + "<BR/>";
				}
				messageError = messageError
						+ "Le nombre de recaves n'est pas au bon format pour le joueur en position "
						+ position;
			}
			try {
				resultGain = Integer.parseInt(resultGainString);
			} catch (NumberFormatException e) {
				error = true;
				if (!"".equals(messageError)) {
					messageError = messageError + "<BR/>";
				}
				messageError = messageError
						+ "Le gain n'est pas au bon format pour le joueur en position "
						+ position;
			}
			if (!error) {
				Resultat resultat = new Resultat(key, position, resultRecave,
						resultAddOn, resultGain);
				resultats.add(resultat);
				miseCalculee = miseCalculee + buyin;
				miseCalculee = miseCalculee + (resultRecave * recave);
				if (resultAddOn) {
					miseCalculee = miseCalculee + addon;
				}
				miseDistribuee = miseDistribuee + resultGain;
			}
		}

		if (!error) {
			if (!miseCalculee.equals(miseDistribuee)) {
				error = true;
				messageError = "Incohérence : total des mise des joueurs = "
						+ miseCalculee + " / total des gains = "
						+ miseDistribuee;
			}
		}

		if (error) {
			JoueurDAO jDAO = new JoueurDAO();
			joueurs = jDAO.findAll();
			Map<String, Object> context = new HashMap<String, Object>();
			for (int position = 1; position < nbJoueurs + 1; position++) {
				context.put("key" + position, (String) ServletActionContext
						.getRequest().getParameter("key" + position));
				context.put("recave" + position, (String) ServletActionContext
						.getRequest().getParameter("recave" + position));
				context.put("addon" + position, (String) ServletActionContext
						.getRequest().getParameter("addon" + position));
				context.put("gain" + position, (String) ServletActionContext
						.getRequest().getParameter("gain" + position));
			}
			ActionContext.getContext().getValueStack().push(context);
			tournoi = newValue;
			return INPUT;
		} else {
			ResultatDAO rDAO = new ResultatDAO();
			TournoiDAO tDAO = new TournoiDAO();
			Key key = KeyFactory.stringToKey(keyTournoi);
			tournoi = tDAO.findById(key);
			List<Resultat> vraisResultats = rDAO.findByTournoi(tournoi);
			for (Resultat vr : vraisResultats) {
				rDAO.delete(vr);
			}
			tournoi = tDAO.update(tournoi, newValue);
			for (Resultat resultat : resultats) {
				resultat.setKeyTournoi(tournoi.getId());
				rDAO.save(resultat);
			}
			resultatsTries = new ArrayList<Resultat>(resultats);
			Collections.sort(resultatsTries, new ResultatComparator());
			return SUCCESS;
		}
	}

	public String supprimer() {
		TournoiDAO tDAO = new TournoiDAO();
		ResultatDAO rDAO = new ResultatDAO();
		Key key = KeyFactory.stringToKey(keyTournoi);
		tournoi = tDAO.findById(key);
		List<Resultat> results = rDAO.findByTournoi(tournoi);
		if (results != null) {
			for (Resultat resultat : results) {
				rDAO.delete(resultat);
			}
		}
		tDAO.delete(tournoi);
		tournois = tDAO.findAll();
		return SUCCESS;
	}

	public String info() {
		TournoiDAO tDAO = new TournoiDAO();
		ResultatDAO rDAO = new ResultatDAO();
		Key key = KeyFactory.stringToKey(keyTournoi);
		tournoi = tDAO.findById(key);
		List<Resultat> results = rDAO.findByTournoi(tournoi);
		totalRecaves = 0;
		totalAddOns = 0;
		totalMise = 0;
		if (results != null) {
			resultatsTries = new ArrayList<Resultat>(results);
			Collections.sort(resultatsTries, new ResultatComparator());
			for (Resultat resultat : results) {
				totalMise = totalMise + resultat.getTournoi().getBuyin();
				totalRecaves = totalRecaves + resultat.getNbRecaves();
				if (resultat.isAddon()) {
					totalAddOns++;
					totalMise = totalMise + resultat.getTournoi().getAddon();
				}
				totalMise = totalMise
						+ (resultat.getNbRecaves() * resultat.getTournoi()
								.getRecave());
			}
		}
		return SUCCESS;
	}

	/**
	 * Initialisation de la liste des saisons : si c'est pour la création ou
	 * modification (booléen), on ajoute la saison n+1 et on initialise par
	 * défaut la saisons proposée à n
	 * 
	 * @param creation
	 */
	private void initSaisons(List<Tournoi> all, boolean creation) {
		saisons = new ArrayList<Integer>();
		for (Tournoi tournoi : all) {
			if (tournoi.getSaison() != null
					&& !saisons.contains(tournoi.getSaison())) {
				saisons.add(tournoi.getSaison());
			}
		}
		if (saisons.size() == 0) {
			saisons.add(1);
		}
		Collections.sort(saisons);
		if (creation) {
			saison = saisons.get(saisons.size() - 1);
			saisons.add(saison + 1);
		}
	}

	public List<Tournoi> getTournois() {
		return tournois;
	}

	public void setTournois(List<Tournoi> tournois) {
		this.tournois = tournois;
	}

	public String getDateString() {
		return dateString;
	}

	public void setDateString(String dateString) {
		this.dateString = dateString;
	}

	public String getBuyinString() {
		return buyinString;
	}

	public void setBuyinString(String buyinString) {
		this.buyinString = buyinString;
	}

	public String getRecaveString() {
		return recaveString;
	}

	public void setRecaveString(String recaveString) {
		this.recaveString = recaveString;
	}

	public String getAddonString() {
		return addonString;
	}

	public void setAddonString(String addonString) {
		this.addonString = addonString;
	}

	public Tournoi getTournoi() {
		return tournoi;
	}

	public void setTournoi(Tournoi tournoi) {
		this.tournoi = tournoi;
	}

	public String getKeyTournoi() {
		return keyTournoi;
	}

	public void setKeyTournoi(String keyTournoi) {
		this.keyTournoi = keyTournoi;
	}

	public boolean isError() {
		return error;
	}

	public void setError(boolean error) {
		this.error = error;
	}

	public String getMessageError() {
		return messageError;
	}

	public void setMessageError(String messageError) {
		this.messageError = messageError;
	}

	public String getNbJoueursString() {
		return nbJoueursString;
	}

	public void setNbJoueursString(String nbJoueursString) {
		this.nbJoueursString = nbJoueursString;
	}

	public List<Joueur> getJoueurs() {
		return joueurs;
	}

	public void setJoueurs(List<Joueur> joueurs) {
		this.joueurs = joueurs;
	}

	public List<Resultat> getResultatsTries() {
		return resultatsTries;
	}

	public void setResultatsTries(List<Resultat> resultatsTries) {
		this.resultatsTries = resultatsTries;
	}

	public Integer getTotalRecaves() {
		return totalRecaves;
	}

	public void setTotalRecaves(Integer totalRecaves) {
		this.totalRecaves = totalRecaves;
	}

	public Integer getTotalAddOns() {
		return totalAddOns;
	}

	public void setTotalAddOns(Integer totalAddOns) {
		this.totalAddOns = totalAddOns;
	}

	public Integer getTotalMise() {
		return totalMise;
	}

	public void setTotalMise(Integer totalMise) {
		this.totalMise = totalMise;
	}

	public Integer getSaison() {
		return saison;
	}

	public void setSaison(Integer saison) {
		this.saison = saison;
	}

	public List<Integer> getSaisons() {
		return saisons;
	}

	public void setSaisons(List<Integer> saisons) {
		this.saisons = saisons;
	}

	public String getSaisonLib() {
		if (saison == null || saison == 0) {
			return "Toutes saisons";
		} else {
			return "Saison " + saison;
		}
	}

}
